// Copyright 2022 jeff.li. and/or its affiliates.

#include <tbir/runtime/container/opaque_object.h>

#include <tbir/runtime/container/opaque_object_private.h>
#include <tbir/runtime/memory.h>
#include <tbir/runtime/registry.h>

namespace tbir::runtime {

    /******************************************************************************
     * OpaqueObject container
     *****************************************************************************/
    OpaqueObject::OpaqueObject(int64_t tag, void *ptr, FOpaqueObjectDeleter deleter) {
        auto node = make_object<OpaqueObjectNode>();
        node->tag = tag;
        node->ptr = ptr;
        node->deleter = deleter;
        data_ = std::move(node);
    }

    void *OpaqueObject::GetOpaquePtr() const {
        MX_DPTR(OpaqueObject);
        return d ? d->ptr : nullptr;
    }

    int64_t OpaqueObject::GetTag() const {
        MX_DPTR(OpaqueObject);
        return d ? d->tag : -1;
    }

    int OpaqueObject::GetInternalBufferSize() {
        return OpaqueObjectNode::BUFFER_SIZE;
    }

    unsigned char *OpaqueObject::GetInternalBufferPtr() const {
        MX_DPTR(OpaqueObject);
        return d ? d->buffer : nullptr;
    }

    void OpaqueObject::update(int64_t tag, void *ptr, FOpaqueObjectDeleter deleter) const {
        MX_CHECK_DPTR(OpaqueObject);
        if (d->ptr != nullptr && d->deleter != nullptr && d->ptr != ptr) {
            d->deleter(d->ptr);
        }
        d->tag = tag;
        d->ptr = ptr;
        d->deleter = deleter;
    }

    std::ostream &operator<<(std::ostream &os, OpaqueObject const &n) {
        os << "OpaqueObject(code: " << n.GetTag() << ", ptr: " << n.GetOpaquePtr() << ")";
        return os;
    }

}  // namespace tbir::runtime
